﻿/*/
 * In this file partial classes for ConfigDatabase entities are written.
 * Some properties are added to partial classes. In actual entity class if any property with type int or byte is enumaration then
 * in partial classes new properties are added to convert the int or byte proeprty into proper enum type.
 * e.g. in KinectDevice partial class below propery KinectRuntimeOptions is written to convert the  int propery RuntimeInitializationOptions
 * into proper enum type.
 * All this is done to make the code writing easier when getting or setting the property values.
 * Also extention methods for ObjectSet<T> collection are written to save the entity object in ObjectSet<T> collection property and saving context.
 * And if exception occurred while saving context then removing the added entity object from ObjectSet<T>.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Linq.Expressions;
using Valentia.Kinection.DataTypes;

namespace Valentia.Kinection.Configuration
{
    #region KinectDevice PARTIAL CLASS
    /// <summary>
    /// KinectDevice partial class
    /// </summary>
    public partial class KinectDevice
    {
        /// <summary>
        /// Kinect device runtime option
        /// </summary>
        public KinectRuntimeOptions KinectRuntimeOptions
        {
            get { return (KinectRuntimeOptions)(this.RuntimeInitializationOptions); }
            set { this.RuntimeInitializationOptions = (int)(value); }
        }

        /// <summary>
        /// Kinect device video resolution
        /// </summary>
        public KinectImageResolution KinectVideoResoloution
        {
            get { return (KinectImageResolution)(this.VideoResoloution); }
            set { this.VideoResoloution = (int)(value); }
        }

        /// <summary>
        /// Kinect device depth resolution
        /// </summary>
        public KinectImageResolution KinectDepthResoloution
        {
            get { return (KinectImageResolution)(this.DepthResoloution); }
            set { this.DepthResoloution = (int)(value); }
        }

        /// <summary>
        /// Kinect device skeleton resolution
        /// </summary>
        public KinectImageResolution KinectSkeletonResoloution
        {
            get { return (KinectImageResolution)(this.SkeletonResoloution); }
            set { this.SkeletonResoloution = (int)(value); }
        }

        /// <summary>
        /// Kinect device video image type
        /// </summary>
        public KinectImageType KinectVideoImageType
        {
            get { return (KinectImageType)(this.VideoImageType); }
            set { this.VideoImageType = (int)(value); }
        }

        /// <summary>
        /// Kinect device depth image type
        /// </summary>
        public KinectImageType KinectDepthImageType
        {
            get { return (KinectImageType)(this.DepthImageType); }
            set { this.DepthImageType = (int)(value); }
        }

        /// <summary>
        /// Kinect device runtime options string representation
        /// </summary>
        public String KinectRuntimeOptionsString { get { return this.KinectRuntimeOptions.ToString(); } }
    }
    #endregion

    #region UtilityUserAllowedNotification PARTIAL CLASS
    /// <summary>
    /// UtilityUserAllowedNotification partial class
    /// </summary>
    public partial class UtilityUserAllowedNotification
    {
        /// <summary>
        /// Utility user notification type
        /// </summary>
        public NotificationType NotificationTypeEnm
        {
            get { return (NotificationType)(this.NotificationID); }
            set { this.NotificationID = (int)(value); }
        }
    }
    #endregion

    #region DataUserAllowedSkeletonJoint PARTIAL CLASS
    /// <summary>
    /// DataUserAllowedSkeletonJoint partial class
    /// </summary>
    public partial class DataUserAllowedSkeletonJoint
    {
        /// <summary>
        /// Service client skeleton joint id
        /// </summary>
        public SkeletonJointID SkeletonJointIDEnm
        {
            get { return (SkeletonJointID)(this.JointID); }
            set { this.JointID = (int)(value); }
        }
    }
    #endregion

    #region EXTENTION METHODS FOR ObjectSet<T>
    /// <summary>
    /// Extension Methods class for ObjectSet collection
    /// </summary>
    public static class ExtensionMethods
    {
        /// <summary>
        /// Gets the next ID of the ObjectSet[Table] for new record
        /// </summary>
        /// <typeparam name="TSource">ObjectSet object</typeparam>
        /// <typeparam name="TResult">ObjectSet result</typeparam>
        /// <param name="table">Table</param>
        /// <param name="selector">Expression</param>
        /// <returns></returns>
        public static TResult NextId<TSource, TResult>(this ObjectSet<TSource> table, Expression<Func<TSource, TResult>> selector)
            where TSource : class
        {
            TResult lastId = table.Any() ? table.Max(selector) : default(TResult);

            if (lastId is int)
            {
                lastId = (TResult)(object)(((int)(object)lastId) + 1);
            }
            return lastId;
        }

        /// <summary>
        /// Add in ObjectSet and save changes, if unable to save changes than remove the
        /// attached object from the collection
        /// </summary>
        /// <typeparam name="TEntity">TEntity</typeparam>
        /// <param name="objectSet">ObjectSet object</param>
        /// <param name="context">Config database entities as context.</param>
        /// <param name="obj">ObjectSet entity</param>
        /// <returns>TEntity</returns>
        public static TEntity AddAndSaveChanges<TEntity>(this ObjectSet<TEntity> objectSet, ConfigDatabaseEntities context, TEntity obj)
            where TEntity : class
        {
            bool added = false;
            try
            {
                objectSet.AddObject(obj);
                added = true;

                context.SaveChanges();
                return obj;
            }
            catch
            {
                if (added) { objectSet.Detach(obj); }
                throw;
            }
        }
    }
    #endregion
}
